﻿using System;
using System.Reflection;
using System.Runtime.Serialization;
using System.Text;

namespace ElectronicCommerce.Framework.Web
{
    /// <summary>
    /// Electronic Commerce Exception
    /// exceptionType 是从MessageType中选取的
    /// </summary>
    public class ECException : Exception
    {
        public Enum ExceptionType { get; private set; }

        public ECException(Enum exceptionType)
            : base()
        {
            ExceptionType = exceptionType;
            Init();
        }

        public ECException(Enum exceptionType, string message)
            : base(message)
        {
            ExceptionType = exceptionType;
            Init();
        }

        public ECException(Enum excptionType, string message, Exception inner)
            : base(message, inner)
        {
            ExceptionType = excptionType;
            Init();
        }

        protected ECException(SerializationInfo info, StreamingContext context)
            : base(info, context)
        {
            Type enumType = Assembly.Load(info.GetString("ExceptionTypeAssemblyKey")).GetType(info.GetString("ExceptionTypeTypeKey"));
            ExceptionType = (Enum)Enum.Parse(enumType, info.GetString("ExceptionTypeValueKey"));
        }

        public override void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            base.GetObjectData(info, context);
            info.AddValue("ExceptionTypeAssemblyKey", ExceptionType.GetType().Assembly.FullName);
            info.AddValue("ExceptionTypeTypeKey", ExceptionType.GetType().ToString());
            info.AddValue("ExceptionTypeValueKey", Convert.ToInt32(ExceptionType));
        }

        #region Public Properties

        public string UserAgent { get; set; }

        public string IPAddress { get; set; }

        public string HttpReferrer { get; set; }

        public string HttpVerb { get; set; }

        public string HttpPathAndQuery { get; set; }

        public DateTime CreatedDate { get; set; }

        #endregion

        #region Private helper functions

        private void Init()
        {
            try
            {
                ECContext ecContext = ECContext.Current;

                if (ecContext != null &&
                    ecContext.Context != null &&
                    ecContext.Context.Request != null)
                {
                    if (ecContext.Context.Request.UrlReferrer != null)
                        HttpReferrer = ecContext.Context.Request.UrlReferrer.ToString();

                    if (ecContext.Context.Request.UserAgent != null)
                        UserAgent = ecContext.Context.Request.UserAgent;

                    if (ecContext.Context.Request.UserHostAddress != null)
                        IPAddress = ecContext.Context.Request.UserHostAddress;

                    try
                    {
                        if (ecContext.Context.Request != null
                            && ecContext.Context.Request.RequestType != null)
                            HttpVerb = ecContext.Context.Request.RequestType;
                    }
                    catch (Exception ex)
                    {
                        System.Diagnostics.Debug.WriteLine(ex.ToString());
                    }

                    if (ecContext.Context.Request != null
                        && ecContext.Context.Request.Url != null
                        && ecContext.Context.Request.Url.PathAndQuery != null)
                        HttpPathAndQuery = ecContext.Context.Request.Url.PathAndQuery;

                    if (ecContext.Context.Request != null
                        && ecContext.Context.Request.UrlReferrer != null
                        && ecContext.Context.Request.UrlReferrer.PathAndQuery != null)
                        HttpReferrer = ecContext.Context.Request.UrlReferrer.PathAndQuery;
                }
            }
            catch { }
        }

        #endregion

        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendLine(this.Message);
            sb.AppendLine("\tUserAgent: " + UserAgent);
            sb.AppendLine("\tIPAddress: " + IPAddress);
            sb.AppendLine("\tHttpReferer: " + HttpReferrer);
            sb.AppendLine("\tHttpVerb: " + HttpVerb);
            sb.AppendLine("\tHttpPathAndQuery: " + HttpPathAndQuery);
            sb.AppendLine("\tStackTrace:" + StackTrace);
            return sb.ToString();
        }
    }
}
